from geocoder import ip
from geocoder.ipinfo import IpinfoQuery
from requests import get
from typing import Optional
from rich.table import Table
from rich.console import Console
from utils import (
    config,
    WeatherHours,
    Unit, Language, Hours,
    get_location,
    format_time
)
from utils.type import _WeatherHours

def weather_hours(
        location: Optional[str]=None,
        hours: Hours=24,
        language: Language=None,
        unit: Unit=None
    ) -> list[_WeatherHours]:
    """
    Get weather forcast for multiple hours

    Args:
        location: Location to get weather forcast. Default: `None`
        hours: Number of hours to get weather forcast (must be >= 24). Default: `24`
        language: Language to get weather forcast. Default: `None`
        unit: Unit to get weather forcast. Default: `None`

    Raises:
        ValueError: Hours must be in 24, 72 or 168

    Returns:
        Weather forcast for multiple hours
    """
    if hours not in [24, 72, 168]:
        raise ValueError('Hours must be in 24, 72 or 168')
    # Get location
    if location is None:
        location = 'me'
        g: IpinfoQuery = ip(location, timeout=1)
        loc = ','.join([str(g.latlng[1]), str(g.latlng[0])])
    else:
        loc = get_location(location)
    # Get language and unit
    if language is None:
        language = config.language
    if unit is None:
        unit = config.unit
    # Get qweather api
    base_url = f'{config.base_url}/v7/weather/{hours}h?location={loc}&lang={language}&unit={unit}'
    headers = {'Authorization': f'Bearer {config.token}'}
    # Send request and get response in json format
    resp = get(url=base_url, headers=headers)
    result: WeatherHours = resp.json()
    if 'hourly' in result:
        return result['hourly']

def print_hours(
        table: _WeatherHours,
        hours: Hours=24,
        unit: Unit=None
    ) -> None:
    """
    Print weather forcast for multiple hours with table

    Args:
        table: Weather forcast for multiple hours
        hours: Number of hours to get weather forcast `(must be >= 24)`
        unit: Unit. Defaults to None
    """
    # Check hours
    if hours not in [24, 72, 168]:
        raise ValueError('Hours must be in 24, 72 or 168')
    # Get default unit
    if unit is None:
        unit = config.unit
    # Create Console
    console = Console()
    # Create Table
    t = Table(title=f'🌤️ Weather forcast for {hours} hours', header_style='bold magenta')
    t.add_column('时间', style='bold cyan', justify='center')
    t.add_column('天气', justify='center')
    t.add_column('温度', justify='center')
    t.add_column('风向风力', justify='center')
    t.add_column('降水率', justify='center')
    t.add_column('降水量', style='bold blue', justify='center')
    t.add_column('湿度', style='bold blue', justify='center')
    t.add_column('气压', justify='center')
    t.add_column('云量', justify='center')
    # Get items
    temp_unit = '°C' if unit == 'm' else '°F'
    # Add rows to table
    for hour in table:
        temp_color = 'red' if int(hour['temp']) >= 30 else \
            'yellow' if int(hour['temp']) >= 25 else 'green'
        pop_color = 'red' if int(hour['pop']) >= 70 else \
            'yellow' if int(hour['pop']) >= 50 else 'green'
        t.add_row(
            format_time(hour['fxTime'], '%Y/%m/%d %H:%M'),
            hour['text'],
            f'[bold {temp_color}]{hour["temp"]}{temp_unit}[/]',
            f'{hour["windDir"]} {hour["windScale"]}级',
            f'[bold {pop_color}]{hour["pop"]}%[/]',
            f'{hour["precip"]}mm',
            f'{hour["humidity"]}%',
            f'{hour["pressure"]}hPa',
            f'{hour["cloud"]}%'
        )
    # Print table
    console.print(t)
